# Script to utilize OneDrive for Business / SkyDrive Pro Office 365 with MyDocs
# Created by Tom Gamull / Presidio / @magicalyak  and Tyler Bithell / B2BTech / @B2B_Tech_TB
# 11 May 2014
# added offline functionality - Tom Gamull 2/2014
# Generalized for public use - Tom Gamull 3/2014
# Rewrote logic - Tom Gamull 4/2014


# Most variables are defined here but if you scroll further down you
# will see we have some Drive letters defined that you may want to change
# We use the I: drive for the mapped drive but we also use J: for a temporary one
# We need two because we have to move files when OneDrive breaks

#Prerequisites
# Using Windows7Library Module - http://windowslibrariespsh.codeplex.com/ - you need to put those on your image
# You need to test this for users and with trusted sites/security settings/compatibility mode on IE
# If you uncomment the visible tages for IE for debug and don't see them then you have a security IE issue

$user 			= [Environment]::UserName
$domain 		= [Environment]::UserDomainName

# replace the variables below with your domain and email structure
$ntdomain		= 'CONTOSO'
$ntdomainchild	= 'CHILD'

$urlsite = 'https://contoso-my.sharepoint.com/personal/'  # You should know this, go to office365 and find the correct URL
$mapsite = '\\contoso-my.sharepoint.com@SSL\DavWWWRoot\personal\'  # This could be encoded from the above but perhaps another revision
$localmapsite = '\\contoso.com\VDI\OneDriveTemp$\' # this should be a local file server somewhere, give permissions like roaming profiles

$path = "I:\Downloads"  # We create the Downloads directory so this is a good one to test.  You would have to replace I: elsewhere if you choose a different drive letter
$pathtemp = "J:\Downloads" # We use J: and the same format for the temporary location (this is used if mapping isn't working, files are moved back to onedrive at logon when it works)

# determine variables based on domain names, we assume a root and child domain, use elseif for more complex variations
# if you just have one domain it should always match so it doesn't matter what's in the child domain
if($domain -match $ntdomain) {
	$emaildomain = "contoso.com" # office 365 domain
	$urldomain = "_contoso_com"
    $localdomain = "contoso.com" # local full domain
}
else {
	$emaildomain = "child.contoso.com" # office365 domain
	$urldomain = "_child_contoso_com"
    $localdomain = "child.contoso.com"  # local full domain
}

# These are used by the functions and powershell script

$emailusername = $user + "@" + $emaildomain
$urlFile = $urlsite + $user + $urldomain + "/Documents"
$mapPath = $mapsite + $user + $urldomain + "\Documents"
$localmapPath = $localmapsite + $user + "." + $localdomain
$localmapPathDocs = $localmapPath + "\Documents"

# We are checking to see if the user is a local admin and bypass the script if so
    If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(`

    [Security.Principal.WindowsBuiltInRole] "Administrator"))
	
	{

	Sleep -seconds 5
	
# Function moves files back to Office 365 if we had to use a temporary directory
function MoveFileToFolder ([string]$source,[string]$destination){
    # get a list of source files
    $files = Get-ChildItem -Path $source | ?{!($_.PSIsContainer)}
    # verify if the list of source files is empty
    if ($files -ne $null) {
        foreach ($file in $files) {
        $filename = $file.Name
        $filebase = $file.BaseName
        $fileext = $file.Extension

# verify if destination file exists

        $filenameNU = $filename #<--------- this line moved from inside the 'If' statement
        if (Test-Path (Join-Path $destination $filename)) {
            $n = 0
            while ((Test-Path (Join-Path $destination $filenameNU)) -eq $true)
            {
            $filenameNU = $filebase + "-" + ++$n + $fileext
            }
        }
    Move-Item $file.FullName (Join-Path $destination $filenameNU)
		}
	}	
#define move function to sync
#format to use is
#MoveFileToFolder $args[0] $args[1]
#MoveFileToFolder C\Temp C:\Temp\Archive
}
	
	If(!(Test-Path -Path $path))
		{
		
		# Create the IE com object and logout first
		$ie = new-object -com InternetExplorer.Application 
		#$ie.visible = $true #Uncomment this for debugging 
		$ie.navigate("http://login.microsoftonline.com/logout.srf")
		do {sleep 1} until (-not ($ie.Busy)) 
		$ie.quit()
	
		$ie = new-object -com InternetExplorer.Application
		$ie.navigate("https://login.microsoftonline.com/login.srf") 
		#$ie.visible = $true #Uncomment this for debugging 
		# Wait for the page to finish loading 
		do {sleep 1} until (-not ($ie.Busy)) 
		#while($ie.ReadyState -ne 4) {start-sleep -m 100} # another way to do this
		# We have to click the remember me checkbox before logging in, we also have to have IE be automated for this to work
		try { 
				$ie.document.GetElementById("_link").click()
				do {sleep 1} until (-not ($ie.Busy)) 
			} catch {$null} 
		try { 
				$ie.document.GetElementById("cred_keep_me_signed_in_checkbox").click()
				$ie.document.GetElementById("cred_userid_inputtext").value = $emailusername
				$ie.document.GetElementById("cred_sign_in_button").click()
				do {sleep 1} until (-not ($ie.Busy)) 
			} catch {$null} 
			sleep -seconds 15 # give plenty of time to redirect
            $ie.navigate($urlFile) # open o365 to verify we grab the token
		do {sleep 1} until (-not ($ie.Busy)) 
		sleep -seconds 5 #wait it out for a redirect
		$ie.quit() 

Function MapDrive {
		# we now map the I: drive, if this fails, we present an error to the user (bottom of script)

		NET USE I: $mappath /PERSISTENT:YES

		Sleep -seconds 7  # this is just in case it takes a while
			
			If(!(Test-Path -Path 'I:\My Music'))
				{New-Item "I:\My Music" -type directory}
			If(!(Test-Path -Path 'I:\My Pictures'))
				{New-Item "I:\My Pictures" -type directory}
			If(!(Test-Path -Path 'I:\My Videos'))
				{New-Item "I:\My Videos" -type directory}
			If(!(Test-Path -Path 'I:\Downloads'))
				{New-Item "I:\Downloads" -type directory}
			If(!(Test-Path -Path 'I:\Saved Games'))
				{New-Item "I:\Saved Games" -type directory}
			
        # We have to set these so the favorites views work correctly.  Downloads will look broken but work, all others work	
			Push-Location
			Set-Location 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders'
				Set-ItemProperty . Personal I:\
				Set-ItemProperty . 'My Music' 'I:\My Music'
				Set-ItemProperty . 'My Pictures' 'I:\My Pictures'
				Set-ItemProperty . 'My Video' 'I:\My Videos'
				Set-ItemProperty . '{374DE290-123F-4565-9164-39C4925E467B}' 'I:\Downloads'
			Pop-Location
			Push-Location
			Set-Location 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders'
				Set-ItemProperty . Personal I:\
				Set-ItemProperty . 'My Music' 'I:\My Music'
				Set-ItemProperty . 'My Pictures' 'I:\My Pictures'
				Set-ItemProperty . 'My Video' 'I:\My Videos'
				Set-ItemProperty . '{374DE290-123F-4565-9164-39C4925E467B}' 'I:\Downloads'
			Pop-Location
			Push-Location
			
			# Using Windows7Library Module - http://windowslibrariespsh.codeplex.com/
            # You'll need to have this on the desktop/image
			
			Import-Module Windows7Library
			$DocPath = (Get-KnownFolder "DocumentsLibrary").Path
			$DocTemp = "C:\Users\Template\Documents"
			$DocPub = "C:\Users\Public\Documents"
			$DocNew = "I:\"
			$MusPath = (Get-KnownFolder "MusicLibrary").Path
			$MusTemp = "C:\Users\Template\Music"
			$MusPub = "C:\Users\Public\Music"
			$MusNew = "I:\My Music"
			$VidPath = (Get-KnownFolder "VideosLibrary").Path
			$VidTemp = "C:\Users\Template\Videos"
			$VidPub = "C:\Users\Public\Videos"
			$VidNew = "I:\My Videos"
			$PicPath = (Get-KnownFolder "PicturesLibrary").Path
			$PicTemp = "C:\Users\Template\Pictures"
			$PicPub = "C:\Users\Public\Pictures"
			$PicNew = "I:\My Pictures"
			
			#If (!(Get-LibraryFolder -LibraryPath $DocPath = $DocNew))
			#
			Add-LibraryFolder -LibraryPath $DocPath -FolderPath $DocNew
			Set-Library -LibraryPath $DocPath -DefaultSaveFolder $DocNew
			Remove-LibraryFolder -LibraryPath $DocPath -FolderPath $DocTemp
			Remove-LibraryFolder -LibraryPath $DocPath -FolderPath $DocPub
			#}
			
			#If (!(Get-LibraryFolder -LibraryPath $MusPath = $MusNew))
			#{
			Add-LibraryFolder -LibraryPath $MusPath -FolderPath $MusNew
			Set-Library -LibraryPath $MusPath -DefaultSaveFolder $MusNew
			Remove-LibraryFolder -LibraryPath $MusPath -FolderPath $MusTemp
			Remove-LibraryFolder -LibraryPath $MusPath -FolderPath $MusPub
			#}
			
			#If (!(Get-LibraryFolder -LibraryPath $VidPath = $VidNew))
			#{
			Add-LibraryFolder -LibraryPath $VidPath -FolderPath $VidNew
			Set-Library -LibraryPath $VidPath -DefaultSaveFolder $VidNew
			Remove-LibraryFolder -LibraryPath $VidPath -FolderPath $VidTemp
			Remove-LibraryFolder -LibraryPath $VidPath -FolderPath $VidPub
			#}
			
			#If (!(Get-LibraryFolder -LibraryPath $PicPath = $PicNew))
			#{
			Add-LibraryFolder -LibraryPath $PicPath -FolderPath $PicNew
			Set-Library -LibraryPath $PicPath -DefaultSaveFolder $PicNew
			Remove-LibraryFolder -LibraryPath $PicPath -FolderPath $PicTemp
			Remove-LibraryFolder -LibraryPath $PicPath -FolderPath $PicPub
			#}
			
			Remove-LibraryFolder -LibraryPath $DocPath -FolderPath "C:\Users\$([Environment]::UserName)\Documents"
			Remove-LibraryFolder -LibraryPath $MusPath -FolderPath "C:\Users\$([Environment]::UserName)\Music"
			Remove-LibraryFolder -LibraryPath $VidPath -FolderPath "C:\Users\$([Environment]::UserName)\Videos"
			Remove-LibraryFolder -LibraryPath $PicPath -FolderPath "C:\Users\$([Environment]::UserName)\Pictures"
}

Function MapTempDrive {
		# we now map the J: drive to local storage as a temporary location
		# location is in DFSR (you can change the redirect location) it is on APS-FS01 at the moment
        # Ensure the variables used below are defined in the beginning
        New-Item -Path $localmapPath -type Directory
        New-Item -Path $localmapPathDocs -type Directory
        NET USE J: $localmapPathDocs /PERSISTENT:YES

		Sleep -seconds 7  # this is just in case it takes a while
			
			If(!(Test-Path -Path 'J:\My Music'))
				{New-Item "J:\My Music" -type directory}
			If(!(Test-Path -Path 'J:\My Pictures'))
				{New-Item "J:\My Pictures" -type directory}
			If(!(Test-Path -Path 'J:\My Videos'))
				{New-Item "J:\My Videos" -type directory}
			If(!(Test-Path -Path 'J:\Downloads'))
				{New-Item "J:\Downloads" -type directory}
			If(!(Test-Path -Path 'J:\Saved Games'))
				{New-Item "J:\Saved Games" -type directory}
				
			Push-Location
			Set-Location 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders'
				Set-ItemProperty . Personal J:\
				Set-ItemProperty . 'My Music' 'J:\My Music'
				Set-ItemProperty . 'My Pictures' 'J:\My Pictures'
				Set-ItemProperty . 'My Video' 'J:\My Videos'
				Set-ItemProperty . '{374DE290-123F-4565-9164-39C4925E467B}' 'J:\Downloads'
			Pop-Location
			Push-Location
			Set-Location 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders'
				Set-ItemProperty . Personal J:\
				Set-ItemProperty . 'My Music' 'J:\My Music'
				Set-ItemProperty . 'My Pictures' 'J:\My Pictures'
				Set-ItemProperty . 'My Video' 'J:\My Videos'
				Set-ItemProperty . '{374DE290-123F-4565-9164-39C4925E467B}' 'J:\Downloads'
			Pop-Location
			Push-Location
			
			# Using Windows7Library Module - http://windowslibrariespsh.codeplex.com/
			
			Import-Module Windows7Library
			$DocPath = (Get-KnownFolder "DocumentsLibrary").Path
			$DocTemp = "C:\Users\Template\Documents"
			$DocPub = "C:\Users\Public\Documents"
			$DocNew = "J:\"
			$MusPath = (Get-KnownFolder "MusicLibrary").Path
			$MusTemp = "C:\Users\Template\Music"
			$MusPub = "C:\Users\Public\Music"
			$MusNew = "J:\My Music"
			$VidPath = (Get-KnownFolder "VideosLibrary").Path
			$VidTemp = "C:\Users\Template\Videos"
			$VidPub = "C:\Users\Public\Videos"
			$VidNew = "J:\My Videos"
			$PicPath = (Get-KnownFolder "PicturesLibrary").Path
			$PicTemp = "C:\Users\Template\Pictures"
			$PicPub = "C:\Users\Public\Pictures"
			$PicNew = "J:\My Pictures"
			
			#If (!(Get-LibraryFolder -LibraryPath $DocPath = $DocNew))
			#
			Add-LibraryFolder -LibraryPath $DocPath -FolderPath $DocNew
			Set-Library -LibraryPath $DocPath -DefaultSaveFolder $DocNew
			Remove-LibraryFolder -LibraryPath $DocPath -FolderPath $DocTemp
			Remove-LibraryFolder -LibraryPath $DocPath -FolderPath $DocPub
			#}
			
			#If (!(Get-LibraryFolder -LibraryPath $MusPath = $MusNew))
			#{
			Add-LibraryFolder -LibraryPath $MusPath -FolderPath $MusNew
			Set-Library -LibraryPath $MusPath -DefaultSaveFolder $MusNew
			Remove-LibraryFolder -LibraryPath $MusPath -FolderPath $MusTemp
			Remove-LibraryFolder -LibraryPath $MusPath -FolderPath $MusPub
			#}
			
			#If (!(Get-LibraryFolder -LibraryPath $VidPath = $VidNew))
			#{
			Add-LibraryFolder -LibraryPath $VidPath -FolderPath $VidNew
			Set-Library -LibraryPath $VidPath -DefaultSaveFolder $VidNew
			Remove-LibraryFolder -LibraryPath $VidPath -FolderPath $VidTemp
			Remove-LibraryFolder -LibraryPath $VidPath -FolderPath $VidPub
			#}
			
			#If (!(Get-LibraryFolder -LibraryPath $PicPath = $PicNew))
			#{
			Add-LibraryFolder -LibraryPath $PicPath -FolderPath $PicNew
			Set-Library -LibraryPath $PicPath -DefaultSaveFolder $PicNew
			Remove-LibraryFolder -LibraryPath $PicPath -FolderPath $PicTemp
			Remove-LibraryFolder -LibraryPath $PicPath -FolderPath $PicPub
			#}
			
			Remove-LibraryFolder -LibraryPath $DocPath -FolderPath "C:\Users\$([Environment]::UserName)\Documents"
			Remove-LibraryFolder -LibraryPath $MusPath -FolderPath "C:\Users\$([Environment]::UserName)\Music"
			Remove-LibraryFolder -LibraryPath $VidPath -FolderPath "C:\Users\$([Environment]::UserName)\Videos"
			Remove-LibraryFolder -LibraryPath $PicPath -FolderPath "C:\Users\$([Environment]::UserName)\Pictures"
}
			
			# Run the function to map the drive
			If(!(Test-Path -Path $path))
				{MapDrive}

							
			# This is in case mapping didn't work so we map to a temporary location and display a message indicating what occurred
			If(!(Test-Path -Path $path))
				{
				MapTempDrive #map the J: drive
				New-EventLog -LogName Application -Source "Drive Mapping"
				Write-EventLog -LogName Application -Source "Drive Mapping" -EntryType Error -EventId 900 -Message "$([Environment]::UserName) has not mapped my documents correctly."
				$MsgBox = New-Object -ComObject wscript.shell
				$MsgBox.Popup("My Documents mapping to OneDrive in Office365 is currently unavailable.  A temporary drive is being used. Any files saved on that drive will be merged with Office 365 when it is available.",0,"Drive Mapping Error",4096+16+0)
				#logoff
				}
                Else
                {
				If((Test-Path -Path $pathtemp))
					{	
					MoveFileToFolder J:\ I:\
					MoveFileToFolder 'J:\My Music' 'I:\My Music'
					MoveFileToFolder 'J:\My Pictures' 'I:\My Pictures'
					MoveFileToFolder 'J:\My Videos' 'I:\My Videos'
					MoveFileToFolder 'J:\Downloads' 'I:\Downloads'
					MoveFileToFolder 'J:\Saved Games' 'I:\Saved Games'
					
					#clear mapped drive, we don't need it anymore
					NET USE J: /delete 
					
					#user now has I: drive mapped and J: was synched to it.
					}
          		# We display an information message indicating mapping worked and we have a 30 second timer to close the box
                # Uncomment next two lines if desired
    			#$MsgBox = New-Object -ComObject wscript.shell
	    		#$MsgBox.Popup("My Documents mapping to your OneDrive in Office365 was successful.  By default, Office documents will save to your OneDrive in Office365.",30,"Drive Mapping Success",4096+64+0)
                }
		}
	Else
		{
		# We have the I: drive working in this option
		# Check to see if J: exists (it ought to persist) and then move files from J: to I:
		If((Test-Path -Path $pathtemp) -and (Test-Path -Path $path))
			{	
			MoveFileToFolder J:\ I:\
			MoveFileToFolder 'J:\My Music' 'I:\My Music'
			MoveFileToFolder 'J:\My Pictures' 'I:\My Pictures'
			MoveFileToFolder 'J:\My Videos' 'I:\My Videos'
			MoveFileToFolder 'J:\Downloads' 'I:\Downloads'
			MoveFileToFolder 'J:\Saved Games' 'I:\Saved Games'
			
			#clear mapped drive, we don't need it anymore
			NET USE J: /delete 
			
			#user now has I: drive mapped and J: was synched to it.
			}
		# We display an information message indicating mapping worked and we have a 30 second timer to close the box
        # Uncomment next two lines if desired
    			#$MsgBox = New-Object -ComObject wscript.shell
	    		#$MsgBox.Popup("My Documents mapping to your OneDrive in Office365 was successful.  By default, Office documents will save to your OneDrive in Office365.",30,"Drive Mapping Success",4096+64+0)
		}
	}
	